package com.smart.seckilldemo.service.impl;

import com.smart.seckilldemo.commons.Parameters;
import com.smart.seckilldemo.commons.exception.ServiceException;
import com.smart.seckilldemo.commons.exception.StatusCode;
import com.smart.seckilldemo.mapper.SeckillGoodsMapper;
import com.smart.seckilldemo.service.InventorySeckillGoods;
import com.smart.seckilldemo.service.LockRedisService;
import com.smart.seckilldemo.service.SeckillGoodsService;
import com.smart.seckilldemo.utils.RedisJudgeUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;


/**
 * 商品 减库存锁事务
 */
@Slf4j
@Service
public class InventorySeckillGoodsImpl implements InventorySeckillGoods {

    @Resource
    LockRedisService lockRedisService;
    @Resource
    SeckillGoodsService seckillGoodsService;
    @Resource
    SeckillGoodsMapper seckillGoodsMapper;
    @Resource
    RedisJudgeUtils redisJudgeUtils;
    @Resource
    RedisTemplate redisTemplate;


    /**
     * 加锁 减库存
     * @param userId 用户
     * @param goodsId 商品
     * @param
     * @return
     */
    @Override
    public Boolean InventorySeckillGoods(Long userId, Long goodsId) {
        //库存缓存key
        String RedisKey=Parameters.SeckillGoodInventory +":"+ goodsId;
        //分布式锁
        String RedisLock=Parameters.Lock+":"+goodsId;
        //定义锁
        Boolean lock=false;
        //尝试获取锁
        try {
            if(lockRedisService.tryLock(RedisLock)){
                //减库存
                Long decrement = redisTemplate.opsForValue().decrement(RedisKey);
                if(decrement<1){
                    //失败则还原库存
                    throw new ServiceException(StatusCode.SECKILL_NULL_ERROR);
                }else {
                    lock=true;
                }
            }
        }catch (Exception e){
            //失败则还原库存
            redisTemplate.opsForValue().increment(RedisKey);
            log.info("锁未释放");
            return false;
        }finally {
            //释放锁
            lockRedisService.unlock(RedisLock);
        }
        return lock;
    }
}
